home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / dvibook / Dviconcat / dviconcat.c < prev    next >
C/C++ Source or Header  |  1994-03-18  |  17KB  |  757 lines

  1. /*
  2.  * Copyright (c) 1987, 1989 University of Maryland
  3.  * Department of Computer Science.  All rights reserved.
  4.  * Permission to copy for any purpose is hereby granted
  5.  * so long as this copyright notice remains intact.
  6.  */
  7.  
  8. #ifndef lint
  9. static char rcsid[] = "$Header: /usr/src/local/tex/local/mctex/dvi/RCS/dviconcat.c,v 3.1 89/08/22 17:23:15 chris Exp $";
  10. #endif
  11.  
  12. /*
  13.  * DVI page concatenation program.
  14.  */
  15.  
  16. #include "libtex/types.h"
  17. #include "libtex/dviclass.h"
  18. #include "libtex/dvicodes.h"
  19. #include "libtex/error.h"
  20. #include "libtex/fio.h"
  21. #include "libtex/gripes.h"
  22. #include "libtex/search.h"
  23. #include <stdio.h>
  24. #include <ctype.h>
  25.  
  26. char *ProgName;
  27. extern char *optarg;
  28. extern int optind;
  29.  
  30. /*
  31.  * We use the following structure to keep track of fonts we have seen.
  32.  * The final DVI file lists all the fonts used in each of the input
  33.  * files.
  34.  */
  35. struct fontinfo {
  36.     struct    fontinfo *fi_next;/* next in list */
  37.     i32    fi_index;    /* font number in output file */
  38.     i32    fi_checksum;    /* the checksum */
  39.     i32    fi_mag;        /* the magnification */
  40.     i32    fi_designsize;    /* the design size */
  41.     short    fi_n1;        /* the name header length */
  42.     short    fi_n2;        /* the name body length */
  43.     char    *fi_name;    /* the name itself */
  44. } *fonts;
  45.  
  46. struct    search *FontFinder;    /* input indicies to ptr-to-fontinfo */
  47. i32    NextOutputFontIndex;    /* generates output indicies */
  48. i32    OutputFontIndex;    /* current (new) index in ouput */
  49.  
  50. char    *DVIFileName;        /* the current input file name */
  51. FILE    *inf;            /* the current input DVI file */
  52. FILE    *outf;            /* the output DVI file */
  53.  
  54. int    errs;            /* counts non-fatal errors */
  55.  
  56. long    StartOfLastPage;    /* The file position just before we started
  57.                    the last page (this is later written to
  58.                    the output file as the previous page
  59.                    pointer). */
  60. long    CurrentPosition;    /* The current position of the file */
  61.  
  62. int    NumberOfOutputPages;    /* number of pages in new DVI file */
  63.  
  64. i32    Numerator;        /* numerator from current DVI file */
  65. i32    Denominator;        /* denominator from current DVI file */
  66. i32    DVIMag;            /* magnification from current DVI file */
  67.  
  68. i32    OutputNumerator;    /* numerator from first DVI file */
  69. i32    OutputDenominator;    /* denominator from first DVI file */
  70. i32    OutputMag;        /* magnification from first DVI file or arg */
  71.  
  72. i32    TallestPageHeight;    /* max of all tallest-page-height values */
  73. i32    WidestPageWidth;    /* max of all widest-page-widths */
  74. i16    DVIStackSize;        /* max of all stack sizes */
  75.  
  76. /* save some string space: we use this a lot */
  77. char    writeerr[] = "error writing DVI file";
  78.  
  79. char    *malloc(), *realloc();
  80. /*
  81.  * You may get lint warnings about sprintf's return value.
  82.  * Older versions of 4BSD have `char *sprintf()'.  ANSI and
  83.  * SysV use `int sprintf()'; so ignore the warnings.
  84.  */
  85.  
  86. /*
  87.  * Lint gets somewhat confused over putc.
  88.  */
  89. #ifdef lint
  90. #define putc(c, f) fputc((int) c, f)
  91. #endif
  92.  
  93. /*
  94.  * Start a page (process a DVI_BOP).
  95.  */
  96. void
  97. BeginPage()
  98. {
  99.     register i32 t;
  100.     register int i;
  101.  
  102.     OutputFontIndex = -1;    /* new page requires respecifying font */
  103.     putbyte(outf, DVI_BOP);
  104.     /* copy the count registers */
  105.     for (i = 10; --i >= 0;) {
  106.         fGetLong(inf, t);
  107.         PutLong(outf, t);
  108.     }
  109.     (void) GetLong(inf);    /* previous page pointer */
  110.     PutLong(outf, StartOfLastPage);
  111.     if (ferror(outf))
  112.         error(1, -1, writeerr);
  113.  
  114.     StartOfLastPage = CurrentPosition;
  115.     CurrentPosition += 45;    /* we just wrote this much */
  116. }
  117.  
  118. /*
  119.  * End a page (process a DVI_EOP).
  120.  */
  121. void
  122. EndPage()
  123. {
  124.  
  125.     putbyte(outf, DVI_EOP);
  126.     if (ferror(outf))
  127.         error(1, -1, writeerr);
  128.     CurrentPosition++;
  129.     NumberOfOutputPages++;
  130. }
  131.  
  132. /*
  133.  * Write a font definition to the output file.
  134.  */
  135. void
  136. WriteFont(fi)
  137.     register struct fontinfo *fi;
  138. {
  139.     register int l;
  140.     register char *s;
  141.  
  142.     if (fi->fi_index < 256) {
  143.         putbyte(outf, DVI_FNTDEF1);
  144.         putbyte(outf, fi->fi_index);
  145.         CurrentPosition += 2;
  146.     } else if (fi->fi_index < 65536) {
  147.         putbyte(outf, DVI_FNTDEF2);
  148.         PutWord(outf, fi->fi_index);
  149.         CurrentPosition += 3;
  150.     } else if (fi->fi_index < 16777216) {
  151.         putbyte(outf, DVI_FNTDEF3);
  152.         Put3Byte(outf, fi->fi_index);
  153.         CurrentPosition += 4;
  154.     } else {
  155.         putbyte(outf, DVI_FNTDEF4);
  156.         PutLong(outf, fi->fi_index);
  157.         CurrentPosition += 5;
  158.     }
  159.     PutLong(outf, fi->fi_checksum);
  160.     PutLong(outf, fi->fi_mag);
  161.     PutLong(outf, fi->fi_designsize);
  162.     putbyte(outf, fi->fi_n1);
  163.     putbyte(outf, fi->fi_n2);
  164.     l = fi->fi_n1 + fi->fi_n2;
  165.     CurrentPosition += 14 + l;
  166.     s = fi->fi_name;
  167.     while (--l >= 0)
  168.         putbyte(outf, *s++);
  169. }
  170.  
  171. /*
  172.  * Write the postamble for the concatenation of all the input files.
  173.  */
  174. void
  175. WritePostAmble()
  176. {
  177.     register struct fontinfo *fi;
  178.     register i32 postpos = CurrentPosition;    /* remember for later */
  179.  
  180.     /* POST p n d m h w s pages */
  181.     putbyte(outf, DVI_POST);
  182.     PutLong(outf, StartOfLastPage);
  183.     PutLong(outf, OutputNumerator);
  184.     PutLong(outf, OutputDenominator);
  185.     PutLong(outf, OutputMag);
  186.     PutLong(outf, TallestPageHeight);
  187.     PutLong(outf, WidestPageWidth);
  188.     PutWord(outf, DVIStackSize);
  189.     PutWord(outf, NumberOfOutputPages);
  190.     CurrentPosition += 29;            /* count all those `put's */
  191.  
  192.     for (fi = fonts; fi != NULL; fi = fi->fi_next)
  193.         WriteFont(fi);
  194.  
  195.     putbyte(outf, DVI_POSTPOST);
  196.     PutLong(outf, postpos);
  197.     putbyte(outf, DVI_VERSION);
  198.     putbyte(outf, DVI_FILLER);
  199.     putbyte(outf, DVI_FILLER);
  200.     putbyte(outf, DVI_FILLER);
  201.     putbyte(outf, DVI_FILLER);
  202.     CurrentPosition += 10;
  203.     while (CurrentPosition & 3) {
  204.         putbyte(outf, DVI_FILLER);
  205.         CurrentPosition++;
  206.     }
  207.     if (ferror(outf))
  208.         error(1, -1, writeerr);
  209. }
  210.  
  211. /*
  212.  * Read the information we need from the postamble for the current DVI file.
  213.  */
  214. void
  215. HandlePostAmble()
  216. {
  217.     register i32 t;
  218.     register i16 w;
  219.  
  220.     (void) GetLong(inf);    /* previous page pointer */
  221.     if (GetLong(inf) != Numerator) {
  222.         error(0, 0,
  223.             "%s: postamble's numerator does not match preamble's",
  224.             DVIFileName);
  225.         errs++;
  226.     }
  227.     if (GetLong(inf) != Denominator) {
  228.         error(0, 0,
  229.             "%s: postamble's denominator does not match preamble's",
  230.             DVIFileName);
  231.         errs++;
  232.     }
  233.     if (GetLong(inf) != DVIMag) {
  234.         error(0, 0,
  235.             "%s: postamble's magnification does not match preamble's",
  236.             DVIFileName);
  237.         errs++;
  238.     }
  239.  
  240.     /*
  241.      * Find maximum of tallest page height, widest page width, and
  242.      * stack size.
  243.      */
  244.     t = GetLong(inf);
  245.     if (t > TallestPageHeight)
  246.         TallestPageHeight = t;
  247.     t = GetLong(inf);
  248.     if (t > WidestPageWidth)
  249.         WidestPageWidth = t;
  250.     w = GetWord(inf);
  251.     if (w > DVIStackSize)
  252.         DVIStackSize = w;
  253.  
  254.     /*
  255.      * The remainder of the file---number of pages, list of fonts,
  256.      * postpost, pointer, version, and filler---we simply ignore.
  257.      */
  258. }
  259.  
  260. /*
  261.  * Handle a preamble.
  262.  * `firstone' is true if this is the first input file.
  263.  * Return true iff something is wrong with the file.
  264.  */
  265. int
  266. HandlePreAmble(firstone)
  267.     int firstone;
  268. {
  269.     register int n, c;
  270.     static char warn1[] = "%s: Warning: preamble %s of %ld";
  271.     static char warn2[] = "does not match first file's value of %ld";
  272.  
  273.     if (getc(inf) != DVI_PRE) {
  274.         error(0, 0, "%s does not begin with a preamble", DVIFileName);
  275.         error(0, 0, "(are you sure it is a DVI file?)");
  276.         errs++;
  277.         return (1);
  278.     }
  279.     if (getc(inf) != DVI_VERSION) {
  280.         error(0, 0, "%s is not a DVI version %d file", DVIFileName,
  281.             DVI_VERSION);
  282.         errs++;
  283.         return (1);
  284.     }
  285.  
  286.     /* committed to DVI file: now most errors are fatal */
  287.     if (firstone) {
  288.         OutputNumerator = Numerator = GetLong(inf);
  289.         OutputDenominator = Denominator = GetLong(inf);
  290.     } else {
  291.         Numerator = GetLong(inf);
  292.         if (Numerator != OutputNumerator) {
  293.             error(0, 0, warn1, DVIFileName, "numerator",
  294.                 (long)Numerator);
  295.             error(0, 0, warn2, (long)OutputNumerator);
  296.             errs++;
  297.         }
  298.         Denominator = GetLong(inf);
  299.         if (Denominator != OutputDenominator) {
  300.             error(0, 0, warn1, DVIFileName, "denominator",
  301.                 (long)Denominator);
  302.             error(0, 0, warn2, (long)OutputDenominator);
  303.             errs++;
  304.         }
  305.     }
  306.     DVIMag = GetLong(inf);
  307.     if (OutputMag == 0)
  308.         OutputMag = DVIMag;
  309.     else if (DVIMag != OutputMag) {
  310.         error(0, 0,
  311.             "%s: Warning: magnification of %ld changed to %ld",
  312.             DVIFileName, (long)DVIMag, (long)OutputMag);
  313.         errs++;
  314.     }
  315.     n = UnSign8(GetByte(inf));    /* comment length */
  316.     if (firstone) {
  317.         putbyte(outf, DVI_PRE);
  318.         putbyte(outf, DVI_VERSION);
  319.         PutLong(outf, Numerator);
  320.         PutLong(outf, Denominator);
  321.         PutLong(outf, OutputMag);
  322.  
  323.         CurrentPosition = 15 + n;    /* well, almost */
  324.         putbyte(outf, n);
  325.         while (--n >= 0) {
  326.             c = GetByte(inf);
  327.             putbyte(outf, c);
  328.         }
  329.     } else {
  330.         while (--n >= 0)
  331.             (void) GetByte(inf);
  332.     }
  333.     return (0);
  334. }
  335.  
  336. /*
  337.  * Read one DVI file, concatenating it with the previous one (if any)
  338.  * or starting up the output file (otherwise).
  339.  */
  340. void
  341. doit(name, fp)
  342.     char *name;
  343.     FILE *fp;
  344. {
  345.     static int started;
  346.  
  347.     DVIFileName = name;
  348.     inf = fp;
  349.     if (HandlePreAmble(started ? 0 : 1))
  350.         return;
  351.     SClear(FontFinder);
  352.     HandleDVIFile();
  353.     HandlePostAmble();
  354.     started = 1;
  355. }
  356.  
  357. main(argc, argv)
  358.     int argc;
  359.     register char **argv;
  360. {
  361.     register int c;
  362.     register char *s;
  363.     FILE *f;
  364.  
  365.     ProgName = *argv;
  366.  
  367.     /*
  368.      * Handle arguments.
  369.      */
  370.     while ((c = getopt(argc, argv, "m:o:")) != EOF) {
  371.         switch (c) {
  372.  
  373.         case 'm':
  374.             if (OutputMag)
  375.                 goto usage;
  376.             OutputMag = atoi(optarg);
  377.             break;
  378.  
  379.         case 'o':
  380.             if (outf != NULL)
  381.                 goto usage;
  382.             if ((outf = fopen(optarg, "w")) == NULL)
  383.                 error(1, -1, "cannot write %s", optarg);
  384.             break;
  385.  
  386.         case '?':
  387. usage:
  388.             (void) fprintf(stderr,
  389.                 "Usage: %s [-m mag] [-o outfile] [files]\n",
  390.                 ProgName);
  391.             (void) fflush(stderr);
  392.             exit(1);
  393.         }
  394.     }
  395.  
  396.     /* setup */
  397.     if (outf == NULL)
  398.         outf = stdout;
  399.     if ((FontFinder = SCreate(sizeof(struct fontinfo *))) == 0)
  400.         error(1, 0, "cannot create font finder (out of memory?)");
  401.     StartOfLastPage = -1;
  402.  
  403.     /*
  404.      * Concatenate the named input file(s).
  405.      * We write a preamble based on the first input file.
  406.      */
  407.     if (optind >= argc)
  408.         doit("`stdin'", stdin);
  409.     else {
  410.         for (c = optind; c < argc; c++) {
  411.             s = argv[c];
  412.             if (*s == '-' && s[1] == 0)
  413.                 doit("`stdin'", stdin);
  414.             else if ((f = fopen(s, "r")) == NULL) {
  415.                 error(0, -1, "cannot read %s", s);
  416.                 errs++;
  417.             } else {
  418.                 doit(s, f);
  419.                 (void) fclose(f);
  420.             }
  421.         }
  422.     }
  423.     if (CurrentPosition)
  424.         WritePostAmble();
  425.  
  426.     (void) fprintf(stderr, "Wrote %d page%s, %ld bytes\n",
  427.         NumberOfOutputPages, NumberOfOutputPages == 1 ? "" : "s",
  428.         (long)CurrentPosition);
  429.     exit(errs ? 2 : 0);
  430.     /* NOTREACHED */
  431. }
  432.  
  433. /*
  434.  * Handle a font definition.
  435.  */
  436. HandleFontDef(index)
  437.     i32 index;
  438. {
  439.     register struct fontinfo *fi;
  440.     register int i;
  441.     register char *s;
  442.     register i32 checksum, mag, designsize;
  443.     register int n1, n2;
  444.     struct fontinfo **p;
  445.     char *name;
  446.     int d = S_CREATE | S_EXCL;
  447.  
  448.     if ((p = (struct fontinfo **)SSearch(FontFinder, index, &d)) == NULL)
  449.         if (d & S_COLL)
  450.             error(1, 0, "font %ld already defined", (long)index);
  451.         else
  452.             error(1, 0, "cannot stash font %ld (out of memory?)",
  453.                 (long)index);
  454.  
  455.     /* collect the font information */
  456.     checksum = GetLong(inf);
  457.     mag = GetLong(inf);
  458.     designsize = GetLong(inf);
  459.     n1 = UnSign8(GetByte(inf));
  460.     n2 = UnSign8(GetByte(inf));
  461.     i = n1 + n2;
  462.     if ((s = malloc((unsigned)i)) == NULL)
  463.         GripeOutOfMemory(i, "font name");
  464.     for (name = s; --i >= 0;)
  465.         *s++ = GetByte(inf);
  466.     s = name;
  467.  
  468.     /*
  469.      * We have not seen the font before in this input file,
  470.      * but we may have seen it in a previous file, so we
  471.      * must search.
  472.      */
  473.     i = n1 + n2;
  474.     for (fi = fonts; fi != NULL; fi = fi->fi_next) {
  475.         if (fi->fi_designsize == designsize &&
  476.             fi->fi_mag == mag &&
  477.             fi->fi_n1 == n1 && fi->fi_n2 == n2 &&
  478.             bcmp(fi->fi_name, s, i) == 0) {
  479.             if (fi->fi_checksum == 0)
  480.                 fi->fi_checksum = checksum;
  481.             else if (checksum && fi->fi_checksum != checksum) {
  482.                 error(0, 0, "\
  483. %s: Warning: font checksum mismatch for %.*s detected",
  484.                     DVIFileName, i, s);
  485.                 errs++;
  486.             }
  487.             *p = fi;
  488.             return;
  489.         }
  490.     }
  491.     /* it is really new; add it to the list */
  492.     if ((fi = (struct fontinfo *)malloc(sizeof *fi)) == NULL)
  493.         GripeOutOfMemory(sizeof *fi, "font information");
  494.     fi->fi_next = fonts;
  495.     fi->fi_index = NextOutputFontIndex++;
  496.     fi->fi_checksum = checksum;
  497.     fi->fi_mag = mag;
  498.     fi->fi_designsize = designsize;
  499.     fi->fi_n1 = n1;
  500.     fi->fi_n2 = n2;
  501.     fi->fi_name = s;
  502.     fonts = fi;
  503.     WriteFont(fi);
  504.     *p = fi;
  505. }
  506.  
  507. /*
  508.  * Handle a \special.
  509.  */
  510. HandleSpecial(c, l, p)
  511.     int c;
  512.     register int l;
  513.     register i32 p;
  514. {
  515.     register int i;
  516.  
  517.     putbyte(outf, c);
  518.     switch (l) {
  519.  
  520.     case DPL_UNS1:
  521.         putbyte(outf, p);
  522.         CurrentPosition += 2;
  523.         break;
  524.  
  525.     case DPL_UNS2:
  526.         PutWord(outf, p);
  527.         CurrentPosition += 3;
  528.         break;
  529.  
  530.     case DPL_UNS3:
  531.         Put3Byte(outf, p);
  532.         CurrentPosition += 4;
  533.         break;
  534.  
  535.     case DPL_SGN4:
  536.         PutLong(outf, p);
  537.         CurrentPosition += 5;
  538.         break;
  539.  
  540.     default:
  541.         panic("HandleSpecial l=%d", l);
  542.         /* NOTREACHED */
  543.     }
  544.     CurrentPosition += p;
  545.     while (--p >= 0) {
  546.         i = getc(inf);
  547.         putbyte(outf, i);
  548.     }
  549.     if (feof(inf))
  550.         GripeUnexpectedDVIEOF();
  551.     if (ferror(outf))
  552.         error(1, -1, writeerr);
  553. }
  554.  
  555. UseFont(index)
  556.     register i32 index;
  557. {
  558.     struct fontinfo *fi, **p;
  559.     int look = S_LOOKUP;
  560.  
  561.     p = (struct fontinfo **)SSearch(FontFinder, index, &look);
  562.     if (p == NULL)
  563.         error(1, 0, "%s requested font %ld without defining it",
  564.             (long)index);
  565.     if ((fi = *p) == NULL)
  566.         panic("null entry in FontFinder for %ld", (long)index);
  567.     index = fi->fi_index;
  568.     if (index < 64) {
  569.         putbyte(outf, index + DVI_FNTNUM0);
  570.         CurrentPosition++;
  571.     } else if (index < 256) {
  572.         putbyte(outf, DVI_FNT1);
  573.         putbyte(outf, index);
  574.         CurrentPosition += 2;
  575.     } else if (index < 65536) {
  576.         putbyte(outf, DVI_FNT2);
  577.         PutWord(outf, index);
  578.         CurrentPosition += 3;
  579.     } else if (index < 16777216) {
  580.         putbyte(outf, DVI_FNT3);
  581.         Put3Byte(outf, index);
  582.         CurrentPosition += 4;
  583.     } else {
  584.         putbyte(outf, DVI_FNT4);
  585.         PutLong(outf, index);
  586.         CurrentPosition += 5;
  587.     }
  588. }
  589.  
  590. /*
  591.  * The following table describes the length (in bytes) of each of the DVI
  592.  * commands that we can simply copy, starting with DVI_SET1 (128).
  593.  */
  594. char    oplen[128] = {
  595.     2, 3, 4, 5,        /* DVI_SET1 .. DVI_SET4 */
  596.     9,            /* DVI_SETRULE */
  597.     2, 3, 4, 5,        /* DVI_PUT1 .. DVI_PUT4 */
  598.     9,            /* DVI_PUTRULE */
  599.     1,            /* DVI_NOP */
  600.     0,            /* DVI_BOP */
  601.     0,            /* DVI_EOP */
  602.     1,            /* DVI_PUSH */
  603.     1,            /* DVI_POP */
  604.     2, 3, 4, 5,        /* DVI_RIGHT1 .. DVI_RIGHT4 */
  605.     1,            /* DVI_W0 */
  606.     2, 3, 4, 5,        /* DVI_W1 .. DVI_W4 */
  607.     1,            /* DVI_X0 */
  608.     2, 3, 4, 5,        /* DVI_X1 .. DVI_X4 */
  609.     2, 3, 4, 5,        /* DVI_DOWN1 .. DVI_DOWN4 */
  610.     1,            /* DVI_Y0 */
  611.     2, 3, 4, 5,        /* DVI_Y1 .. DVI_Y4 */
  612.     1,            /* DVI_Z0 */
  613.     2, 3, 4, 5,        /* DVI_Z1 .. DVI_Z4 */
  614.     0,            /* DVI_FNTNUM0 (171) */
  615.     0, 0, 0, 0, 0, 0, 0, 0,    /* 172 .. 179 */
  616.     0, 0, 0, 0, 0, 0, 0, 0,    /* 180 .. 187 */
  617.     0, 0, 0, 0, 0, 0, 0, 0,    /* 188 .. 195 */
  618.     0, 0, 0, 0, 0, 0, 0, 0,    /* 196 .. 203 */
  619.     0, 0, 0, 0, 0, 0, 0, 0,    /* 204 .. 211 */
  620.     0, 0, 0, 0, 0, 0, 0, 0,    /* 212 .. 219 */
  621.     0, 0, 0, 0, 0, 0, 0, 0,    /* 220 .. 227 */
  622.     0, 0, 0, 0, 0, 0, 0,    /* 228 .. 234 */
  623.     0, 0, 0, 0,        /* DVI_FNT1 .. DVI_FNT4 */
  624.     0, 0, 0, 0,        /* DVI_XXX1 .. DVI_XXX4 */
  625.     0, 0, 0, 0,        /* DVI_FNTDEF1 .. DVI_FNTDEF4 */
  626.     0,            /* DVI_PRE */
  627.     0,            /* DVI_POST */
  628.     0,            /* DVI_POSTPOST */
  629.     0, 0, 0, 0, 0, 0,    /* 250 .. 255 */
  630. };
  631.  
  632. /*
  633.  * Here we read the input DVI file and copy the pages to the output
  634.  * DVI file, renumbering fonts.  We also keep track of font changes,
  635.  * handle font definitions, and perform some other housekeeping.
  636.  */
  637. HandleDVIFile()
  638. {
  639.     register int c, l;
  640.     register i32 p;
  641.     int doingpage = 0;
  642.  
  643.     /* Only way out is via "return" statement */
  644.     for (;;) {
  645.         c = getc(inf);    /* getc() returns unsigned values */
  646.         if (DVI_IsChar(c)) {
  647.             putbyte(outf, c);
  648.             CurrentPosition++;
  649.             continue;
  650.         }
  651.         if (DVI_IsFont(c)) {    /* note font change */
  652.             UseFont((i32)(c - DVI_FNTNUM0));
  653.             continue;
  654.         }
  655.         if (c == EOF)
  656.             GripeUnexpectedDVIEOF();
  657.         if ((l = (oplen - 128)[c]) != 0) {    /* simple copy */
  658.             CurrentPosition += l;
  659.             putbyte(outf, c);
  660.             while (--l > 0) {
  661.                 c = getc(inf);
  662.                 putbyte(outf, c);
  663.             }
  664.             if (ferror(outf))
  665.                 error(1, -1, writeerr);
  666.             continue;
  667.         }
  668.         if ((l = DVI_OpLen(c)) != 0) {
  669.             /*
  670.              * Handle other generics.
  671.              * N.B.: there should only be unsigned parameters
  672.              * here (save SGN4), for commands with negative
  673.              * parameters have been taken care of above.
  674.              */
  675.             switch (l) {
  676.  
  677.             case DPL_UNS1:
  678.                 p = getc(inf);
  679.                 break;
  680.  
  681.             case DPL_UNS2:
  682.                 fGetWord(inf, p);
  683.                 break;
  684.  
  685.             case DPL_UNS3:
  686.                 fGet3Byte(inf, p);
  687.                 break;
  688.  
  689.             case DPL_SGN4:
  690.                 fGetLong(inf, p);
  691.                 break;
  692.  
  693.             default:
  694.                 panic("HandleDVIFile l=%d", l);
  695.             }
  696.  
  697.             /*
  698.              * Now that we have the parameter, perform the
  699.              * command.
  700.              */
  701.             switch (DVI_DT(c)) {
  702.  
  703.             case DT_FNT:
  704.                 UseFont(p);
  705.                 continue;
  706.  
  707.             case DT_XXX:
  708.                 HandleSpecial(c, l, p);
  709.                 continue;
  710.  
  711.             case DT_FNTDEF:
  712.                 HandleFontDef(p);
  713.                 continue;
  714.  
  715.             default:
  716.                 panic("HandleDVIFile DVI_DT(%d)=%d",
  717.                     c, DVI_DT(c));
  718.             }
  719.             continue;
  720.         }
  721.  
  722.         switch (c) {    /* handle the few remaining cases */
  723.  
  724.         case DVI_BOP:
  725.             if (doingpage)
  726.                 GripeUnexpectedOp("BOP (during page)");
  727.             BeginPage();
  728.             doingpage = 1;
  729.             break;
  730.  
  731.         case DVI_EOP:
  732.             if (!doingpage)
  733.                 GripeUnexpectedOp("EOP (outside page)");
  734.             EndPage();
  735.             doingpage = 0;
  736.             break;
  737.  
  738.         case DVI_PRE:
  739.             GripeUnexpectedOp("PRE");
  740.             /* NOTREACHED */
  741.  
  742.         case DVI_POST:
  743.             if (doingpage)
  744.                 GripeUnexpectedOp("POST (inside page)");
  745.             return;
  746.  
  747.         case DVI_POSTPOST:
  748.             GripeUnexpectedOp("POSTPOST");
  749.             /* NOTREACHED */
  750.  
  751.         default:
  752.             GripeUndefinedOp(c);
  753.             /* NOTREACHED */
  754.         }
  755.     }
  756. }
  757.